package com.qfedu.mtl.util.web;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

/**
 * 前端总控制器，接受前端用户请求，根据客户端的请求URL查找 和执行对应的处理器方法。  /   /api/user/login.do
 */
@WebServlet("/api/*")
public class DispatcherServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取映射表（这个映射表是保存到 ServletContext 全局作用域中， 其中key 就是URL_HANDLER_MAP ，保存是在监听器中完成的。 ）
        Map<String, HandlerInfo> urlHandlerMap = (Map<String, HandlerInfo> )this.getServletContext().getAttribute("URL_HANDLER_MAP");
        //2.获得用户请求路径（从求对象中获取，http协议请求头中第一行 ）
        String requestURI = req.getRequestURI();
        //3.如果请求URL包含查询字符串，处理掉 比如我们的请求可能是  /api/user/login.do?username=admin&password=123 但是需要的只是 ？以前的路径。
        if (requestURI.indexOf("?")!=-1) {
            //获取到？符号的位置
            int index = requestURI.indexOf("?");
            //从0到下标位置截取 比如 /api/user/login.do
            requestURI  = requestURI.substring(0, index);
        }
        //4.根据请求路径 从映射表中获得处理器信息,但是这里需要注意的是我们需要去掉核心控制器的请求前缀 /api ,因为映射表中是没有这个前缀的。
        String urlKey = requestURI.replace("/api", "");
        HandlerInfo info = urlHandlerMap.get(urlKey);
        //5.如果没有查询到处理器信息，输出一些提示信息
        if (info ==null) {
            resp.setCharacterEncoding("utf-8");
            resp.setContentType("text/html;charset=utf-8");
            resp.getWriter().println("<h1 style='color:red'>Error,No Mapping Handler[错误,该请求没有匹配到处理器方法喔，注意检查!]</h1>");
            resp.getWriter().println("<h5 style='color:green'>下面是成功映射的列表：<h5>");
            for (String url : urlHandlerMap.keySet()) {
                resp.getWriter().println("<p>/api" +url +"->"+ urlHandlerMap.get(url).getMethod()+"<p>");
            }
            return;
        }
        //6.如果找到处理器信息
        try {
            //6.1.取出处理器类对象，创建对象。
            Object obj = info.getCls().newInstance();
            //6.2.执行 处理器方法（这里是反射方式调用方法）传入参数，这里执行的就是 Controller中的方法。
            info.getMethod().invoke(obj,req,resp);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
}
